package com.pan.annotation.aspect;

import com.pan.annotation.OrderItemsCheck;
import com.pan.entity.Goods;
import com.pan.entity.Result;
import com.pan.excep.error.AspectException;
import com.pan.feign.GoodsFeign;
import com.pan.tools.ArrayTools;
import com.pan.vo.OrderItemVo;
import io.swagger.models.auth.In;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;

@Aspect
@Component
public class OrderItemsCheckAspect {


    @Resource
    private GoodsFeign goodsFeign;

    @Pointcut("@annotation(com.pan.annotation.OrderItemsCheck)")
    public void annotationCut(){}


    @Before("annotationCut()")
    public void check(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        OrderItemsCheck orderItemsCheck = methodSignature.getMethod().getAnnotation(OrderItemsCheck.class);
        String name = orderItemsCheck.value();
        String[] names = methodSignature.getParameterNames();
        Integer index = ArrayTools.indexOf(names, name);
        if (index == null) {
            throw new AspectException(500, "找不到orderItems参数", OrderItemsCheck.class, methodSignature.getMethod());
        }
        Object[] args = joinPoint.getArgs();
        List<OrderItemVo> orderItemVos = (List<OrderItemVo>) args[index];
        List<Long> idList = new ArrayList<>(orderItemVos.stream().map(OrderItemVo::getGoodsId).collect(Collectors.toCollection(HashSet::new)));
        Result<List<Goods>> goodsListResult = goodsFeign.selectGoodsList(idList);
        List<Goods> goodsList = goodsListResult.getData();

        Map<Long, Double> goodsMap = goodsList.stream().collect(Collectors.toMap(Goods::getId,Goods::getPrice));
        Predicate<OrderItemVo> isPrice = orderItemVo -> {
            Optional<Double> price = Optional.ofNullable(goodsMap.get(orderItemVo.getGoodsId()));
            return price.isPresent()?orderItemVo.getTotalAmount().compareTo(price.get()*orderItemVo.getGoodsCount())==0:false;
        };
        if (!orderItemVos.stream().anyMatch(isPrice)){
            throw new AspectException(403,"购买商品数据异常",OrderItemsCheck.class,methodSignature.getMethod());
        }

    }
}
